﻿using System.ComponentModel.DataAnnotations;
using System.Collections.Generic;
using System.Linq;
using System;

namespace GameSchoolApplication.Models
{
	// Represents a Student's participation in a Game
    public class StudentPoints
	{
		[Key]
		public int EnrollmentId { get; set; }

		public int StudentId	{ get; set; }
		public int GameId		{ get; set; }
		public int? Points		{ get; set; }
		public decimal? Grade	{ get; set; }
		public string UserName	{ get; set; }
		public string Name		{ get; set; }
        [ForeignKey("StudentId")]
        public virtual Person Student { get; set; }
        [ForeignKey("GameId")]
        public virtual Game Game { get; set; }

        public IEnumerable<StudentLevelPoints> LevelEntries
        {
            get
            {
                return Game.Levels.SelectMany(l => l.StudentLevelPoints).Where(sl => sl.StudentId == StudentId);
            }
        }

        public StudentLevelPoints CurrentLevel
        {
            get
            {
                return LevelEntries.OrderBy(le => le.Id).LastOrDefault();
            }
        }

        public Tuple<StudentPoints, StudentPoints> NearestPoints
        {
            get
            {
                if (Points.HasValue)
                {
                    var inPointOrder = Game.Enrollments.OrderByDescending(e => e.Points);
                    return Tuple.Create(
                        inPointOrder.Where(e => e.Points > Points).LastOrDefault(),
                        inPointOrder.Where(e => e.Points < Points).FirstOrDefault()
                    );
                }
                else
                {
                    return Tuple.Create(Game.Enrollments.Where(e => e.Points != null).OrderBy(e => e.Points).FirstOrDefault(), (StudentPoints)null);
                }
            }
        }
	}

	// Represents a Student's participation in a Level
    public class StudentLevelPoints
	{
        public StudentLevelPoints()
        {
            this.StartedAt = DateTime.Now;
        }

		public int Id			{ get; set; }
		public int StudentId	{ get; set; }
		public int LevelId		{ get; set; }
		public int? Points		{ get; set; }
        public DateTime StartedAt { get; set; }
        [ForeignKey("StudentId")]
        public virtual Person Student { get; set; }
        [ForeignKey("LevelId")]
        public virtual Level Level { get; set; }

        public IEnumerable<StudentAssignmentPoints> AssignmentPoints
        {
            get
            {
                return Level.Assignments.SelectMany(a => a.StudentAssignmentPoints).Where(sa => sa.StudentId == StudentId);
            }
        }

        public IEnumerable<StudentTestPoints> TestPoints
        {
            get
            {
                return Level.Tests.SelectMany(t => t.StudentTestPoints).Where(st => st.StudentId == StudentId);
            }
        }

        public IEnumerable<Assignment> PendingAssignments
        {
            get
            {
                return Level.Assignments.Where(a => !AssignmentPoints.Select(ap => ap.AssignmentId).Contains(a.AssignmentId));
            }
        }

        public IEnumerable<Test> PendingTests
        {
            get
            {
                return Level.Tests.Where(t => !TestPoints.Select(tp => tp.TestId).Contains(t.TestId));
            }
        }

        public Tuple<StudentLevelPoints, StudentLevelPoints> NearestPoints
        {
            get
            {
                if (Points.HasValue)
                {
                    var inPointOrder = Level.StudentLevelPoints.OrderByDescending(e => e.Points);
                    return Tuple.Create(
                        inPointOrder.Where(e => e.Points > Points).LastOrDefault(),
                        inPointOrder.Where(e => e.Points < Points).FirstOrDefault()
                    );
                }
                else
                {
                    return Tuple.Create(Level.StudentLevelPoints.Where(e => e.Points != null).OrderBy(e => e.Points).FirstOrDefault(), (StudentLevelPoints)null);
                }
            }
        }
    }

	// Represents a Student's 
    public class StudentAssignmentPoints
	{
		public int Id			{ get; set; }
		public int StudentId	{ get; set; }
		public int AssignmentId { get; set; }
        [Display(Name = "Stig")]
		public int? Points		{ get; set; }
        [Display(Name = "Skráarnafn")]
        public string FileName  { get; set; }
        [ForeignKey("StudentId")]
        public virtual Person Student { get; set; }
        [ForeignKey("AssignmentId")]
        public virtual Assignment Assignment { get; set; }

        public StudentLevelPoints LevelEntry
        {
            get
            {
                return Student.LevelParticipations.Where(sl => sl.LevelId == Assignment.LevelId).SingleOrDefault();
            }
        }
	}

	public class StudentTestPoints
	{
		public int Id			{ get; set; }
		public int StudentId	{ get; set; }
		public int TestId		{ get; set; }
		public int? Points		{ get; set; }
        [ForeignKey("StudentId")]
        public virtual Person Student { get; set; }
        [ForeignKey("TestId")]
        public virtual Test Test { get; set; }
        public virtual ICollection<StudentAnswer> StudentAnswers { get; set; }

        public StudentLevelPoints LevelEntry
        {
            get
            {
                return Student.LevelParticipations.Where(sl => sl.LevelId == Test.LevelId).SingleOrDefault();
            }
        }
	}

	public class StudentCheatPoints
	{
		public int Id			{ get; set; }
		public int? GameId		{ get; set; }
		public int? StudentId	{ get; set; }
		public int? CheatPoints	{ get; set; }

		[ForeignKey("StudentId")]
		public virtual Person Student { get; set; }

		[ForeignKey("GameId")]
		public virtual Game Game	  { get; set; }

		public virtual ICollection<Cheat> Cheat { get; set; }
	}

}